package com.jlsoft.zltd;

import android.content.Intent;
import android.view.KeyEvent;
import android.view.View;
import android.webkit.ValueCallback;
import android.webkit.WebView;

import com.zltd.decoder.DecoderManager;

import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaInterface;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.CordovaResourceApi;
import org.apache.cordova.CordovaWebView;
import org.apache.cordova.CordovaWebViewEngine;
import org.apache.cordova.ICordovaCookieManager;
import org.apache.cordova.LOG;
import org.apache.cordova.NativeToJsMessageQueue;
import org.apache.cordova.PluginManager;
import org.apache.cordova.PluginResult;
import org.json.JSONException;
import org.json.JSONObject;

import java.lang.reflect.Field;

/**
 * 智联天地pda扫码
 */
public class ZltdPDA extends CordovaPlugin implements DecoderManager.IDecoderStatusListener {

  protected static int RETURN_CAMERA_CONN_ERR = 0x103;
  private DecoderManager mDecoderMgr;
  private CallbackContext callbackContext;
  private CordovaWebView webView;
  private CordovaInterface cordova;

  @Override
  public void initialize(CordovaInterface cordova, CordovaWebView webView) {
    this.cordova = cordova;
    this.webView = webView;

    onKeyListenerProxy();

    //1.创建DecoderManager
    try {
      mDecoderMgr = DecoderManager.getInstance();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  @Override
  public boolean execute(String action, String rawArgs, CallbackContext callbackContext) throws JSONException {
    if (mDecoderMgr == null) return false;
    if ("registerListener".equals(action)) {
      return registerListener(callbackContext);
    } else if ("unregisterListener".equals(action)) {
      this.callbackContext = null;
      return true;
    } else if ("keyDown".equals(action)) {
      KeyEvent keyEvent = new KeyEvent(KeyEvent.ACTION_DOWN, 96);
      this.mDecoderMgr.dispatchScanKeyEvent(keyEvent);
      return true;
    } else if ("keyUp".equals(action)) {
      KeyEvent keyEvent = new KeyEvent(KeyEvent.ACTION_DOWN, 23);
      this.mDecoderMgr.dispatchScanKeyEvent(keyEvent);
      return true;
    } else if ("close".equals(action)) {
      this.callbackContext = null;
      this.close();
      return true;
    }
    return false;
  }

  private boolean registerListener(CallbackContext callbackContext) {
    this.callbackContext = callbackContext;
    return true;
  }

  @Override
  public void onDecoderStatusChanage(int i) {
  }

  @Override
  public void onDecoderResultChanage(String s, String s1) {
    if (!s.startsWith("Decode is interruptted")) {
      Intent intent = new Intent();
      intent.setAction("com.android.server.scannerservice.broadcast");
      intent.putExtra("scannerdata", s);
      this.cordova.getActivity().sendBroadcast(intent);
    }
  }

  @Override
  public void onResume(boolean multitasking) {
    super.onResume(multitasking);
    this.connect();
  }

  private void connect() {
    if (mDecoderMgr != null) {
      //2.连接扫描服务
      try {
        int res = mDecoderMgr.connectDecoderSRV();

        if (res == RETURN_CAMERA_CONN_ERR) {
          return;
        }

        //3.为Decodermanager添加一个扫描回调接口,用来接收扫描返回数据
        mDecoderMgr.addDecoderStatusListener(this);
        mDecoderMgr.setDataTransferType(3);
        mDecoderMgr.setScanMode(2);
      } catch (Exception e) {
        e.printStackTrace();
        mDecoderMgr = null;
      }
    }
  }

  @Override
  public void onPause(boolean multitasking) {
    super.onPause(multitasking);
    this.close();
  }

  private void close() {
    // 4.在App不工作或者退到后台之后,有必要释放资源,关闭或者移除扫描服务
    if (mDecoderMgr != null) {
      mDecoderMgr.removeDecoderStatusListener(this);
      mDecoderMgr.stopDecode();
      mDecoderMgr.disconnectDecoderSRV();
    }
  }

  @Override
  public void onDestroy() {
    mDecoderMgr = null;
    super.onDestroy();
  }

  /**
   * 用代理来解决按键监听的问题
   */
  public void onKeyListenerProxy() {
    if (this.webView == null) return;

    String webViewClassName = this.webView.getClass().getName();
    CordovaWebViewEngine engine = this.webView.getEngine();
    try {
      if ("org.apache.cordova.CordovaWebViewImpl".equals(webViewClassName)) {
        Class webViewEngineClass = Class.forName(engine.getClass().getName());
        Field engineField = webViewEngineClass.getDeclaredField("client");
        engineField.setAccessible(true);
        CordovaWebViewEngine.Client client = (CordovaWebViewEngine.Client) engineField.get(engine);
        client = new EngineClient(client);
        engineField.set(engine, client);
      }


    } catch (Exception e) {
      e.printStackTrace();
    }

  }

  /**
   * 代理类
   */
  private class EngineClient implements CordovaWebViewEngine.Client {

    CordovaWebViewEngine.Client client;

    public EngineClient(CordovaWebViewEngine.Client client) {
      this.client = client;
    }

    @Override
    public Boolean onDispatchKeyEvent(KeyEvent event) {
      if (mDecoderMgr != null && mDecoderMgr.getScanMode() == 2 && event.getKeyCode() == 96
        && event.getRepeatCount() == 0) {
        mDecoderMgr.dispatchScanKeyEvent(event);
      }
      return this.client.onDispatchKeyEvent(event);
    }

    @Override
    public void clearLoadTimeoutTimer() {
      this.client.clearLoadTimeoutTimer();
    }

    @Override
    public void onPageStarted(String newUrl) {
      this.client.onPageStarted(newUrl);
    }

    @Override
    public void onReceivedError(int errorCode, String description, String failingUrl) {
      this.client.onReceivedError(errorCode, description, failingUrl);
    }

    @Override
    public void onPageFinishedLoading(String url) {
      this.client.onPageFinishedLoading(url);
    }

    @Override
    public boolean onNavigationAttempt(String url) {
      return this.client.onNavigationAttempt(url);
    }
  }
}
